The present application relates generally to an improved data processing apparatus and method and more specifically to mechanisms for performing aggressive code optimizations with an ability to rollback changes made by the aggressive optimizations.
Typically, for a program to be executed on a computing system, the source code for the program is compiled and linked to generate executable code. As part of the compilation process, a compiler typically performs one or more optimizations on the source code to enable more efficient execution of the program. While the compiler may identify many opportunities to transform the source code so as to optimize its execution, the compiler is typically constrained in the optimizations it can perform or where such optimizations may be applied by the semantics of the source code being compiled.
For example, boundary scenario behavior, which rarely or never actually occurs, limits optimization of code because of the very possibility of the boundary condition existing. That is, because a particular source code statement, when transformed by a particular compiler optimization, may result in a boundary condition occurring, even though it may rarely if ever actually occur during execution, the compiler cannot apply the optimization that might otherwise be able to be applied if this possible boundary condition were not present. Such boundary conditions include, for example, transforming source code into optimized code that spans a memory page boundary and that page is not accessible, i.e. the memory page is either set to be inaccessible either for reading, writing, or both, or the page has been “paged out” meaning stored on an external storage medium and removed from main memory and the page table. For example, one compiler optimization that may be affected by such boundary scenario behavior is the transformation of scalar source code to compiled vector code. The compiler seeks to preserve the behavior of the original source code after such transformations. However, in transforming scalar code to vector code, it is possible that the original scalar code would not have any boundary condition violations when performed using sequential scalar code execution, but when transformed to vector code, which is executed in a parallel manner, may result in a boundary condition violation that may result in incorrect execution of the transformed code with regard to transformed code preserving the original behavior of the source code. Moreover, when transforming code to be executed in a multithreaded environment, the transformed code may introduce a thread level race condition in which two or more threads access the same portion of data in a parallel manner and thus, the writing of the data by one thread may introduce errors into the operation of the other thread or threads.
As a result, when a compiler determines that a boundary condition violation may occur in the transformed code, the compiler typically does not perform the optimization on that portion of code in order to avoid any possibility, no matter how remote, that the transformed code might operate in a different manner from the original source code. Thus, the compiled code is not optimized as much as possible since optimizations are not applied in areas where there is a possibility of a boundary condition violation or other behavior that is not consistent with the original source code.
Alternatively, a user may manually override this compiler behavior and instruct the compiler to ignore these semantics. As a result, the compiler may still make the transformations, but this may result in an erroneous operation of the transformed code. Moreover, users often do not known whether particular semantics in the source code or transformed code are essential and are hesitant to override the compiler's normal behavior.